<?php
/**
 * Author:   tangxiaowen
 * Email:    846506584@qq.com
 * Date:     2021/3/1 0001 11:02
 * Describe: 企业微信 - 回调事件处理类
 */

namespace app\manage\controller\corp;

use think\Controller;
use app\api\model\Task;
use app\common\model\corp\Corp;
use think\exception\ValidateException;
use app\common\server\corp\{Msg, Client, Auth};
use app\common\server\corp\Base as BaseService;
use app\common\server\corp\jdk\{XMLParse, WXBizMsgCrypt};

class Callback extends Controller
{
    protected $failException = true;

    /**
     * SuiteTicket 存储时间/秒
     * @var int
     */
    private $suiteTicketCacheTime = 1200;

    /**
     * 授权回调安装
     */
    public function install()
    {
        $authCode = input('auth_code/s');
        $state = input('state/d');
        (new Auth())->getPermanentByCode($authCode, $state);
        $webUrl = sprintf(config('queue.corp')['redirect_uri_install_web']?? '', $authCode);
        header("Location:{$webUrl}");
    }

    /**
     * 系统回调事件
     * -数据回调|指令回调
     */
    public function receive()
    {
        $msgSignature = input('msg_signature');
        $timestamp = input('timestamp');
        $nonce = input('nonce');
        $echoStr = input('echostr');

        if(!empty($echoStr)){
            $this->Verify($msgSignature, $timestamp, $nonce, $echoStr);
        }

        $postData = file_get_contents("php://input");
        trace(1111111);
        trace($postData);

        if(!empty($postData)){
            $temp = (new XMLParse())->xmlToArray($this->analysisData($msgSignature, $timestamp, $nonce, $postData));
            trace(222222222);
            trace($temp);
            if(isset($temp['InfoType'])){
                switch ($temp['InfoType']){//存储suite_ticket
                    case 'suite_ticket':
                        /** @var \app\common\server\corp\Base getSuiteTicket */
                        cache('suiteTicket', $temp['SuiteTicket'], $this->suiteTicketCacheTime);
                        break;
                    case 'create_auth'://授权
                        (new Auth())->getPermanentByCode($temp['AuthCode']);
                        break;
                    case 'cancel_auth'://取消授权
                        (new Corp())->cancelAuth($temp['AuthCorpId']);
                        break;
                }
            }

            if(isset($temp['MsgType'])){//消息事件
                switch ($temp['MsgType']){
                    case 'event':
                        if(isset($temp['ChangeType']) && $temp['ChangeType'] == 'add_external_contact'){//添加客户事件
                            (new Client())->addClientTag($temp['ToUserName'], $temp['UserID'], $temp['ExternalUserID']);
                            (new Msg())->sendWelcomeMsg($temp['ToUserName'], $temp['WelcomeCode']);
                        }
                        if(isset($temp['ChangeType']) && $temp['ChangeType'] == 'del_external_contact'){//删除客户事件
                        }
                        break;
                }
            }

            echo 'success';die;
        }
    }

    /**
     * 验证
     * @throws  ValidateException
     */
    public function Verify($msgSignature, $timestamp, $nonce, $echoStr)
    {
        $baseService = new BaseService();
        if(!empty($echoStr)){//时间
            $sEchoStr = '';
            $wxb = new WXBizMsgCrypt($baseService->token, $baseService->encodingAeskey, $baseService->corpId);
            $resCode = $wxb->VerifyURL($msgSignature, $timestamp, $nonce, $echoStr, $sEchoStr);
            if($resCode == 0){
                echo $sEchoStr;die;
            }
            $wxb = new WXBizMsgCrypt($baseService->token, $baseService->encodingAeskey, $baseService->suiteId);
            $resCode = $wxb->VerifyURL($msgSignature, $timestamp, $nonce, $echoStr, $sEchoStr);
            if($resCode == 0){
                echo $sEchoStr;die;
            }

            exception('事件回调错误 错误码' . $resCode);
        }
    }

    /**
     * 解析数据
     * @throws ValidateException
     */
    public function analysisData($msgSignature, $timestamp, $nonce, $data)
    {
        $baseService = new BaseService();
        $msg = '';
        $wxb = new WXBizMsgCrypt($baseService->token, $baseService->encodingAeskey, $baseService->corpId);
        $resCode = $wxb->DecryptMsg($msgSignature, $timestamp, $nonce, $data, $msg);
        if($resCode == 0){
            return $msg;
        }

        $wxb = new WXBizMsgCrypt($baseService->token, $baseService->encodingAeskey, $baseService->suiteId);
        $resCode = $wxb->DecryptMsg($msgSignature, $timestamp, $nonce, $data, $msg);
        if($resCode == 0){
            return $msg;
        }

        check_exception('解析数据失败');
    }
}